#include "board.h"
#include<QPainter>
#include<QMouseEvent>
#include<QMessageBox>

#define GetRowCol(__row, __col, __id) \
    int __row = _s[__id]._row;\
    int __col = _s[__id]._col

board::board(QWidget *parent) : QWidget(parent)
{
    for(int i=0;i<32;i++)//初始化棋子
    {
        _s[i].init(i);
    }
    _selectid=-1;//初始化点击
    _bRedTurn=true;
    clickid=-1;//对点击的初始化 //   //
}
void board::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    int d=40;
    _r=d/2;
    for(int i=1;i<=10;i++)
    {
        painter.drawLine(QPoint(d,i*d),QPoint(9*d,i*d));

    }//画十条横线

    painter.drawLine(QPoint(11*d,1*d),QPoint(13*d,1*d));
    painter.drawLine(QPoint(11*d,3*d),QPoint(13*d,3*d));
    painter.drawLine(QPoint(11*d,1*d),QPoint(11*d,3*d));
    painter.drawLine(QPoint(13*d,1*d),QPoint(13*d,3*d));
    painter.drawLine(QPoint(11*d,2*d),QPoint(13*d,2*d));
    //画框
    for(int i=1;i<=9;i++)
    {
        if(i==1||i==9)
        painter.drawLine(QPoint(i*d,d),QPoint(i*d,10*d));
        else
        {
           painter.drawLine(QPoint(i*d,d),QPoint(i*d,5*d));
           painter.drawLine(QPoint(i*d,6*d),QPoint(i*d,10*d));
        }
    }//画9条竖线
    painter.drawLine(QPoint(4*d,1*d),QPoint(6*d,3*d));
    painter.drawLine(QPoint(4*d,3*d),QPoint(6*d,1*d));
    painter.drawLine(QPoint(4*d,8*d),QPoint(6*d,10*d));
    painter.drawLine(QPoint(4*d,10*d),QPoint(6*d,8*d));
    //画九宫格
    for(int i=0;i<32;i++)
    {
        drawstone(painter,i);
    } //绘制32颗棋子
}

QPoint board::center(int row,int col)
{
    QPoint ret;
    ret.rx()=(col+1)*_r*2;
    ret.ry()=(row+1)*_r*2;
    return ret;
}
QPoint board::center(int id)
{
    return center(_s[id]._row,_s[id]._col);
}

void board::drawstone(QPainter&painter, int id)
{
    if(_s[id]._dead==true)
        return;

    QPoint c=center(id);
    QRect rect=QRect(c.x()-_r,c.y()-_r,_r*2,_r*2);

    //画背景
    if(id==_selectid)
    {
        painter.setBrush(QBrush(Qt::yellow));
    }
    else
    {
        painter.setBrush(QBrush(Qt::white));
    }

    //设置字的初始颜色
    painter.setPen(Qt::black);

    painter.drawEllipse(center(id),_r,_r);//调用drawEllipse（椭圆）函数
    if(_s[id]._red)//当该棋子的种类为红时设置棋子的字的颜色为红色
    {
        painter.setPen(Qt::red);
    }
    painter.setFont(QFont("system",_r,700));//修改字体的大小及样式
    painter.drawText(rect,_s[id].getText(),QTextOption(Qt::AlignCenter));//设置字的文本
}


bool board::getRowCol(QPoint pt, int &row, int &col)//设置获取点击的位置
{
    for(row=0;row<=9;row++)
    {
        for(col=0;col<=8;col++)
        {
            QPoint c=center(row,col);
            int dx=c.x()-pt.x();
            int dy=c.y()-pt.y();
            int dist=dx*dx+dy*dy;
            if(dist<_r*_r)
                return true;
        }//使用距离
    }
    return false;
}
int board::getStoneCountAtLine(int row1, int col1, int row2, int col2)
{
    int ret = 0;
    if(row1 != row2 && col1 != col2)
        return -1;
    if(row1 == row2 && col1 == col2)
        return -1;

    if(row1 == row2)
    {
        int min = col1 < col2 ? col1 : col2;
        int max = col1 < col2 ? col2 : col1;
        for(int col = min+1; col<max; ++col)
        {
            if(getStoneId(row1, col) != -1) ++ret;
        }
    }
    else
    {
        int min = row1 < row2 ? row1 : row2;
        int max = row1 < row2 ? row2 : row1;
        for(int row = min+1; row<max; ++row)
        {
            if(getStoneId(row, col1) != -1) ++ret;
        }
    }

    return ret;
}
bool board::isDead(int id)
{
    if(id == -1)return true;
    return _s[id]._dead;
}
int board::relation(int row1, int col1, int row, int col)
{
    return qAbs(row1-row)*10+qAbs(col1-col);
}
int board::getStoneId(int row, int col)
{
    for(int i=0; i<32; ++i)
    {
        if(_s[i]._row == row && _s[i]._col == col && !isDead(i))
            return i;
    }
    return -1;
}
bool board::isBottomSide(int id)
{
    return _bSide == _s[id]._red;
}

bool board::canMoveJIANG(int moveid,int row,int col,int killid)
{
   /*
    //1、首先目标位置在九宫格内2、移动步长为一格；
    if(_s[moveid]._red)
    {
        if(row>2)
            return false;
    }
    else
    {
        if(row<7)
            return false;
    }//判断红和黑的行

    if(col<3)
        return false;
    if(col>5)
        return false;
    //判断列
    //1、首先目标位置在九宫格内

    int dr=_s[moveid]._row-row;
    int dc=_s[moveid]._col-col;
    int d=abs(dr)*10+abs(dc);//abs()为取绝对值
    if(d==1||d==10)
        return true;

    return false;
    */
    if(killid != -1 && _s[killid]._type == stone::JIANG)
        return canMoveCHE(moveid, row, col, killid);

    GetRowCol(row1, col1, moveid);
    int r = relation(row1, col1, row, col);
    if(r != 1 && r != 10) return false;

    if(col < 3 || col > 5) return false;
    if(isBottomSide(moveid))
    {
        if(row < 7) return false;
    }
    else
    {
        if(row > 2) return false;
    }
    return true;
}
bool board::canMoveSHI(int moveid,int row,int col,int)
{
    /*
     if(_s[moveid]._red)
    {
        if(row>2)
            return false;
    }
    else
    {
        if(row<7)
            return false;
    }//判断红和黑的行

    if(col<3)
        return false;
    if(col>5)
        return false;
    //判断列
    //首先目标位置在九宫格内

    int dr=_s[moveid]._row-row;
    int dc=_s[moveid]._col-col;
    int d=abs(dr)*10+abs(dc);//abs()为取绝对值
    if(d==11)
        return true;//走斜线

    return false;
    */
    GetRowCol(row1, col1, moveid);
    int r = relation(row1, col1, row, col);
    if(r != 11) return false;

    if(col < 3 || col > 5) return false;
    if(isBottomSide(moveid))
    {
        if(row < 7) return false;
    }
    else
    {
        if(row > 2) return false;
    }
    return true;
}
bool board::canMoveXIANG(int moveid,int row,int col,int)
{
    /*
    int dr=_s[moveid]._row-row;
    int dc=_s[moveid]._col-col;
    int d=abs(dr)*10+abs(dc);//abs()为取绝对值
    if(d==22)
        return true;//走斜线

    return false;
    //return true;
    */
    GetRowCol(row1, col1, moveid);
    int r = relation(row1, col1, row, col);
    if(r != 22) return false;

    int rEye = (row+row1)/2;
    int cEye = (col+col1)/2;
    if(getStoneId(rEye, cEye) != -1)
        return false;

    if(isBottomSide(moveid))
    {
        if(row < 4) return false;
    }
    else
    {
        if(row > 5) return false;
    }
    return true;
}
bool board::canMoveCHE(int moveid,int row,int col,int)
{
    GetRowCol(row1, col1, moveid);
    int ret = getStoneCountAtLine(row1, col1, row, col);
    if(ret == 0)
        return true;
    return false;
    //return true;
}
bool board::canMoveMA(int moveid,int row,int col,int)
{
    /*
    int dr=_s[moveid]._row-row;
    int dc=_s[moveid]._col-col;
    int d=abs(dr)*10+abs(dc);//abs()为取绝对值
    if(d==12||d==21)
        return true;//走斜线

    return false;
    //return true;
    */
    GetRowCol(row1, col1, moveid);
    int r = relation(row1, col1, row, col);
    if(r != 12 && r != 21)
        return false;

    if(r == 12)
    {
        if(getStoneId(row1, (col+col1)/2) != -1)
            return false;
    }
    else
    {
        if(getStoneId((row+row1)/2, col1) != -1)
            return false;
    }

    return true;
}
bool board::canMovePAO(int moveid,int row,int col,int killid)
{
    //return true;
    GetRowCol(row1, col1, moveid);
    int ret = getStoneCountAtLine(row, col, row1, col1);
    if(killid != -1)
    {
        if(ret == 1) return true;
    }
    else
    {
        if(ret == 0) return true;
    }
    return false;
}
bool board::canMoveBING(int moveid,int row,int col,int)
{
   // return true;
    GetRowCol(row1, col1, moveid);
    int r = relation(row1, col1, row, col);
    if(r != 1 && r != 10) return false;

    if(isBottomSide(moveid))
    {
        if(row > row1) return false;
        if(row1 >= 5 && row == row1) return false;
    }
    else
    {
        if(row < row1) return false;
        if(row1 <= 4 && row == row1) return false;
    }

    return true;
}

bool board::canMove(int moveid,int row,int col,int killid)
{
    if(_s[moveid]._red==_s[killid]._red)//moveid和killid颜色相同
    {
        //换选择
        _selectid=killid;
        update();

        return false;
    }

    switch (_s[moveid]._type)
    {
    case stone::JIANG:
        return canMoveJIANG(moveid,row,col,killid);
        break;
    case stone::SHI:
        return canMoveSHI(moveid,row,col,killid);
        break;
    case stone::XIANG:
        return canMoveXIANG(moveid,row,col,killid);
        break;
    case stone::CHE:
        return canMoveCHE(moveid,row,col,killid);
        break;
    case stone::MA:
        return canMoveMA(moveid,row,col,killid);
        break;
    case stone::PAO:
        return canMovePAO(moveid,row,col,killid);
        break;
    case stone::BING:
        return canMoveBING(moveid,row,col,killid);
        break;
    default:
        break;
    }
    return true;
}

void board::mouseReleaseEvent(QMouseEvent *ev)
{

    QPoint pt=ev->pos();
    //将pt转化为象棋的行列值
    //判断这个行列值上有无棋子
    int row,col;
    bool bRet=getRowCol(pt,row,col);
    if(bRet==false)
        return;//未点击到可识别的位置

    int i;
    int clickid=-1;//对点击的初始化
     for(i=0;i<32;i++)
     {
         if(_s[i]._row==row&&_s[i]._col==col&&_s[i]._dead==false)
         {
             break;
         }
     }
     if(i<32)
     {
         clickid=i;
     }

    if(_selectid==-1)
    {
        if(clickid!=-1)
        {
            if(_bRedTurn==_s[clickid]._red)
            {
               // _selectid=clickid;
               click(pt);//   //
                update();
            }
        }//使得红方为先走的一方
        /*
          if(i<32)
            {
             _selectid=i;
             update();
            }
        */
   }

    else
    {
        if(canMove(_selectid,row,col,clickid))
        {
          //走棋
            _s[_selectid]._row=row;
           _s[_selectid]._col=col;
          if(clickid!=-1)
            {
              //_s[clickid]._dead=true;
              click(pt);//   //
             }
             _selectid = -1;
             _bRedTurn = !_bRedTurn;
              update();
        }
    }
/*
    if(ev->button() != Qt::LeftButton)
    {
        return;
    }

    click(ev->pos());
*/

}
/*void board::gameover(bool isWin)
{
    if(iswin())
    {
        QMessageBox::information(NULL,"gameover","you are the winner!");
    }
}*/
void board::click(int id, int row, int col)
{
    if(this->_selectid == -1)
    {
        _selectid=clickid;//   //
        trySelectStone(id);
    }
    else
    {
        _s[clickid]._dead=true;//  //
        tryMoveStone(id, row, col);
    }
}
//
//
//
void board::click(QPoint pt)
{
    int row, col;
    bool bClicked = getClickRowCol(pt, row, col);
    if(!bClicked) return;

    int id = getStoneId(row, col);
    click(id, row, col);
}
bool board::getClickRowCol(QPoint pt, int &row, int &col)
{
    for(row=0; row<=9; ++row)
    {
        for(col=0; col<=8; ++col)
        {
            QPoint distance = center(row, col) - pt;
            if(distance.x() * distance.x() + distance.y() * distance.y() < _r* _r)
                return true;
        }
    }
    return false;
}
//
//
//
void board::trySelectStone(int id)
{
    if(id == -1)
        return;

    if(!canSelect(id)) return;

    _selectid = id;
    update();
}
void board::tryMoveStone(int killid, int row, int col)
{
    if(killid != -1 && sameColor(killid, _selectid))
    {
        trySelectStone(killid);
        return;
    }

    bool ret = canMove(_selectid, killid, row, col);
    if(ret)
    {
        moveStone(_selectid, killid, row, col);
        _selectid = -1;
        update();
    }
}
bool board::canSelect(int id)
{
    return _bRedTurn == _s[id]._red;
}

void board::moveStone(int moveid, int row, int col)
{
    _s[moveid]._row = row;
    _s[moveid]._col = col;

    _bRedTurn = !_bRedTurn;
}

void board::moveStone(int moveid, int killid, int row, int col)
{
    saveStep(moveid, killid, row, col, _steps);

    killStone(killid);
    moveStone(moveid, row, col);
}
void board::saveStep(int moveid, int killid, int row, int col, QVector<step*>& steps)
{
    GetRowCol(row1, col1, moveid);
    step* _step = new step;
    _step->_colFrom = col1;
    _step->_colTo = col;
    _step->_rowFrom = row1;
    _step->_rowTo = row;
    _step->_moveid = moveid;
    _step->_killid = killid;

    steps.append(_step);
}
bool board::sameColor(int id1, int id2)
{
    if(id1 == -1 || id2 == -1) return false;

    return red(id1) == red(id2);
}
bool board::red(int id)
{
    return _s[id]._red;
}
void board::killStone(int id)
{
    if(id==-1) return;
    _s[id]._dead = true;
}
void board::reliveStone(int id)
{
    if(id==-1) return;
    _s[id]._dead = false;
}


